package com.wizinno.android.urineflow.fragment;

import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import cn.hutool.core.collection.CollectionUtil;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.wizinno.android.urineflow.R;
import com.wizinno.android.urineflow.constant.CommonControl;
import com.wizinno.android.urineflow.constant.FragmentNoConstant;
import com.wizinno.android.urineflow.dialog.CustomDialog;
import com.wizinno.android.urineflow.serialport.SerialPortUtil;
import com.wizinno.android.urineflow.serialport.SerialProtocol;
import com.wizinno.android.urineflow.util.LogUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class DistanceFragment extends BaseFragment {

    private EditText et_near_distance;
    private EditText et_near_time;
    private EditText et_leave_distance;
    private EditText et_leave_time;
    private EditText et_on_distance;
    private EditText et_on_time;
    private EditText et_off_distance;
    private EditText et_off_time;

    private List<EditText> editTexts;

    private Button btn_distance_read;
    private Button btn_distance_write;

    private TextView tv_distance_current;

    private static Button btn_distance_start;
    private static boolean start = false;

    private TextView tv_distance_event;
    private List<String> distanceEventList;

    private static final int COLOR = Color.parseColor("#fe9701");
    private static LineChart lc_distance;
    private static List<Float> lineData;
    private static List<String> lineLabels;

    public DistanceFragment() {
        setNo(FragmentNoConstant.SETTING_DISTANCE);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        btn_distance_read = view.findViewById(R.id.btn_distance_read);
        btn_distance_write = view.findViewById(R.id.btn_distance_write);
        btn_distance_start = view.findViewById(R.id.btn_distance_start);
        tv_distance_current = view.findViewById(R.id.tv_distance_current);

        et_near_distance = view.findViewById(R.id.et_near_distance);
        et_near_time = view.findViewById(R.id.et_near_time);
        et_leave_distance = view.findViewById(R.id.et_leave_distance);
        et_leave_time = view.findViewById(R.id.et_leave_time);
        et_on_distance = view.findViewById(R.id.et_on_distance);
        et_on_time = view.findViewById(R.id.et_on_time);
        et_off_distance = view.findViewById(R.id.et_off_distance);
        et_off_time = view.findViewById(R.id.et_off_time);

        tv_distance_event = view.findViewById(R.id.tv_distance_event);

        DistanceClickListener distanceClickListener = new DistanceClickListener();
        btn_distance_read.setOnClickListener(distanceClickListener);
        btn_distance_write.setOnClickListener(distanceClickListener);
        btn_distance_start.setOnClickListener(distanceClickListener);

        lc_distance = view.findViewById(R.id.lc_distance);
    }

    @Override
    protected void initData() {
        SerialPortUtil.readDistance();
        drawBlankLine();
        distanceEventList = new ArrayList<>();
        editTexts = new ArrayList<>();
        editTexts.add(et_near_distance);
        editTexts.add(et_near_time);
        editTexts.add(et_leave_distance);
        editTexts.add(et_leave_time);
        editTexts.add(et_on_distance);
        editTexts.add(et_on_time);
        editTexts.add(et_off_distance);
        editTexts.add(et_off_time);
        setWritePermission();
    }

    /**
     * 设置写入权限
     */
    private void setWritePermission() {
        if (CommonControl.INSTANCE.isAdmin) {
            //设置按钮可用
            btn_distance_write.setEnabled(true);
            //设置编辑框可用
            for (EditText editText : editTexts) {
                editText.setFocusable(true);
            }
        } else {
            btn_distance_write.setEnabled(false);
            for (EditText editText : editTexts) {
                editText.setFocusable(false);
            }
        }
    }

    private static void drawBlankLine() {
        lineData = new ArrayList<>();
        lineLabels = new ArrayList<>();
        drawLine(lineData, lineLabels);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_distance, container, false);
    }

    public void setDistancePeople(byte[] receiveBytes) {
        Integer peopleNear = SerialPortUtil.byte2TransToInt(receiveBytes[2], receiveBytes[3]);
        Integer peopleLeave = SerialPortUtil.byte2TransToInt(receiveBytes[4], receiveBytes[5]);
        et_near_distance.setText(String.valueOf(peopleNear));
        et_leave_distance.setText(String.valueOf(peopleLeave));
    }

    public void setDistancePeopleTime(byte[] receiveBytes) {
        Integer peopleNearTime = SerialPortUtil.byte2TransToInt(receiveBytes[2], receiveBytes[3]);
        Integer peopleLeaveTime = SerialPortUtil.byte2TransToInt(receiveBytes[4], receiveBytes[5]);
        et_near_time.setText(String.valueOf(peopleNearTime));
        et_leave_time.setText(String.valueOf(peopleLeaveTime));
    }

    public void setDistanceButton(byte[] receiveBytes) {
        Integer buttonNear = SerialPortUtil.byte2TransToInt(receiveBytes[2], receiveBytes[3]);
        Integer buttonLeave = SerialPortUtil.byte2TransToInt(receiveBytes[4], receiveBytes[5]);
        et_on_distance.setText(String.valueOf(buttonNear));
        et_off_distance.setText(String.valueOf(buttonLeave));
    }

    public void setDistanceButtonTime(byte[] receiveBytes) {
        Integer buttonOnTime = SerialPortUtil.byte2TransToInt(receiveBytes[2], receiveBytes[3]);
        Integer buttonOffTime = SerialPortUtil.byte2TransToInt(receiveBytes[4], receiveBytes[5]);
        et_on_time.setText(String.valueOf(buttonOnTime));
        et_off_time.setText(String.valueOf(buttonOffTime));
    }

    public void setDistance(byte[] receiveBytes) {
        int maxX = 100;
        //更新折线图
        int distance = SerialPortUtil.byte2TransToInt(receiveBytes[2], receiveBytes[3]);
        LogUtils.d("接收测距值：" + distance);
        lineData.add((float) distance);
        int size = lineData.size();
        if (size >= maxX) {
            lineData = lineData.subList(size - maxX, size);
        }
        drawLine(lineData, lineLabels);
        tv_distance_current.setText(distance + " mm");
    }

    public void setDistanceEvent(byte event) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String eventStr = format.format(new Date()) + "  ";
        switch (event) {
            case SerialProtocol.NEAR:
                eventStr += SerialProtocol.NEAR_DESC;
                break;
            case SerialProtocol.LEAVE:
                eventStr += SerialProtocol.LEAVE_DESC;
                break;
            case SerialProtocol.ON:
                eventStr += SerialProtocol.ON_DESC;
                break;
            case SerialProtocol.OFF:
                eventStr += SerialProtocol.OFF_DESC;
                break;
        }
        distanceEventList.add(eventStr);
        int size = distanceEventList.size();
        int maxLine = tv_distance_event.getMaxLines();
        if (size > maxLine) {
            distanceEventList = distanceEventList.subList(size - maxLine, size);
        }
        String textValue = "";
        for (String s : distanceEventList) {
            textValue += s + "\n";
        }
        tv_distance_event.setText(textValue);
    }

    class DistanceClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            int viewId = v.getId();
            if (viewId == R.id.btn_distance_read) {
                SerialPortUtil.readDistance();
            } else if (viewId == R.id.btn_distance_write) {
                showDialog();
            } else if (viewId == R.id.btn_distance_start) {
                startDistance(false);
            }
        }
    }

    private void showDialog() {
        CustomDialog customDialog = new CustomDialog(CommonControl.INSTANCE.settingBaseActivity);
        customDialog.setMessage("确认将距离配置参数写入设备？");
        customDialog.setPositiveButton((dialog, which) -> {
            writeDistance();
            dialog.dismiss();
        });
        customDialog.show();
    }

    public static void startDistance(boolean stop) {
        if (stop) {
            start = false;
        } else {
            start = !start;
        }
        if (btn_distance_start != null) {
            if (start) {
                drawBlankLine();
                btn_distance_start.setText("停止测距");
            } else {
                btn_distance_start.setText("开始测距");
            }
            GetDistanceThread getDistanceThread = new GetDistanceThread();
            Thread thread = new Thread(getDistanceThread);
            thread.start();
        }
    }

    private void writeDistance() {
        /**
         * 写入顺序:
         *  按钮ON距离-按钮OFF距离
         *  人靠近距离-人离开距离
         *  按钮ON抖动时间-按钮OFF抖动时间
         *  人靠近抖动时间-人离开抖动时间
         */
        Integer onDistance = Integer.valueOf(et_on_distance.getText().toString());
        Integer offDistance = Integer.valueOf(et_off_distance.getText().toString());
        Integer nearDistance = Integer.valueOf(et_near_distance.getText().toString());
        Integer leaveDistance = Integer.valueOf(et_leave_distance.getText().toString());
        Integer onTime = Integer.valueOf(et_on_time.getText().toString());
        Integer offTime = Integer.valueOf(et_off_time.getText().toString());
        Integer nearTime = Integer.valueOf(et_near_time.getText().toString());
        Integer leaveTime = Integer.valueOf(et_leave_time.getText().toString());
        List<Integer> values = new ArrayList<>();
        values.add(onDistance);
        values.add(offDistance);
        values.add(nearDistance);
        values.add(leaveDistance);
        values.add(onTime);
        values.add(offTime);
        values.add(nearTime);
        values.add(leaveTime);
        SerialPortUtil.writeDistance(values);
    }

    static class GetDistanceThread implements Runnable {
        @Override
        public void run() {
            while (start) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                CommonControl.INSTANCE.usbHelper.usbSendData(SerialProtocol.READ_DISTANCE);
            }
        }
    }

    private static void drawLine(List<Float> lineData, List<String> xLabels) {
        int textSize = 20;
        List<Entry> lineEntryList = new ArrayList<>();

        Description description = lc_distance.getDescription();
        description.setText("");
        Legend legend = lc_distance.getLegend();
        legend.setTextSize(textSize);
        legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
        legend.setForm(Legend.LegendForm.CIRCLE);
        legend.setFormSize(textSize);
        if (CollectionUtil.isNotEmpty(lineData)) {
            for (int i = 0; i < lineData.size(); i++) {
                lineEntryList.add(new Entry(i, lineData.get(i)));
            }
        }
        LineDataSet volSet = new LineDataSet(lineEntryList, "距离(mm)");
        volSet.setLineWidth(1);//折线的宽度
        volSet.setCircleRadius(2.5f);//数据点的半径
        volSet.setCircleColor(COLOR);//数据点的颜色
        volSet.setDrawFilled(false);//是否对数据点圆心进行填充
        volSet.setDrawCircleHole(false);//数据点圆是否为空心圆
        volSet.setColor(COLOR);//设置折线颜色
        volSet.setAxisDependency(YAxis.AxisDependency.LEFT);

        LineData data = new LineData(volSet);
        data.setDrawValues(false);//折线上是否绘制数据

        //左边y轴
        YAxis leftAxis = lc_distance.getAxisLeft();
        leftAxis.setTextColor(COLOR);
        leftAxis.setTextSize(textSize);
        leftAxis.setAxisMinimum(0);
        leftAxis.setDrawGridLines(true);
        leftAxis.setGridColor(Color.parseColor("#1088ff"));

        YAxis rightAxis = lc_distance.getAxisRight();
        rightAxis.setEnabled(false);

        XAxis xAxis = lc_distance.getXAxis();//初始化X轴
        xAxis.setEnabled(true);//是否调用x轴
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);//设置X轴的位置
        xAxis.setTextSize(textSize);//设置标签的字体大小
        xAxis.setTextColor(Color.BLACK);//设置标签字体的颜色
        xAxis.setDrawAxisLine(true);//是否绘制x轴的直线
        xAxis.setDrawGridLines(false);//是否画网格线
        xAxis.setValueFormatter(new IndexAxisValueFormatter(xLabels));
        xAxis.setAxisMinimum(0);
//        xAxis.setGranularity(2);

        //底部偏移量
        lc_distance.setExtraBottomOffset(5f);
        lc_distance.setData(data);
        lc_distance.invalidate();
    }
}